<?php
/**
 * Created by PhpStorm.
 * User: chenx
 * Date: 18-3-22
 * Time: 上午9:56
 */

namespace common\service;


use common\components\HttpClient;

class WechatService extends BaseService
{
    /**
     * 获取openid
     * @param string $code
     * @return bool|mixed
     */
    public static function getWechatOpenid($code = '',$appid = '',$secret = '')
    {

        $getuser_api = "https://api.weixin.qq.com/sns/jscode2session";
        $params = [
            'appid' => $appid,
            'secret' => $secret,
            'js_code' => $code,
            'grant_type' => 'authorization_code'
        ];
        $result = HttpClient::get($getuser_api,$params);
        return $result;
    }

    /**
     * 生成小程序二维码
     * @param string $scene 自定义页面参数
     * @param string $page 指定页面
     * @param int $width 二维码宽度
     * @return false|string
     */
    public static function getWechatQrcode($scene = '',$page ='',$width = 430)
    {
        $access_token = self::getAccessToken();
        if($access_token === false){
            return false;
        }
        $api_url = 'https://api.weixin.qq.com/wxa/getwxacodeunlimit?access_token='.$access_token;
        $params = [
            'scene' => $scene,
            'page' => $page,
            'width' => $width,
        ];
        $result = HttpClient::post($api_url,json_encode($params));
        if(@json_decode($result,true)){
            return false;
        }

        $result = QiniuService::uploadFileByStream($result);
        return $result;
    }

    /**
     * 获取微信access_token
     * @return bool|mixed
     */
    public static function getAccessToken()
    {
        $api_url = 'https://api.weixin.qq.com/cgi-bin/token';
        $appid = \Yii::$app->params['wechat']['appid'];
        $secret = \Yii::$app->params['wechat']['secret'];
        $params = [
            'grant_type' => 'client_credential',
            'appid' => $appid,
            'secret' => $secret,
        ];
        $request =  HttpClient::get($api_url,$params);
        $request = json_decode($request,true);
        if(isset($request['access_token'])){
            return $request['access_token'];
        }
        return false;
    }

    /**
     * 获取微信用户头像文件
     * @param string $url
     * @return bool|string
     */
    public static function getUserHeader($url)
    {
        $stream = HttpClient::get($url);
        $result = QiniuService::uploadFileByStream($stream);
        return $result;
    }

    /**
     * 统一下单接口
     * @param $openid
     * @param string $title
     * @param string $out_trade_no
     * @param int $total
     * @return array|bool
     */
    public static function createUnifiedOrder($openid,$title = '',$out_trade_no= '',$total = 0)
    {
        $lenth = mb_strlen($title,'UTF-8');
        if($lenth>15){
            $title = mb_substr($title,0,15,'UTF-8').'...';
        }
        $url = 'https://api.mch.weixin.qq.com/pay/unifiedorder';
        $now = time();
        $mch_id = \Yii::$app->params['wechat']['mchid'];
        $data = [
            'appid'             =>  \Yii::$app->params['wechat']['appid'], //小程序ID
            'mch_id'            =>  (string)$mch_id, //商户号
            'body'              =>  $title, //商品描述
            'nonce_str'         =>  md5($now),
            'out_trade_no'      =>  $out_trade_no, //商户订单号
            'total_fee'         =>  intval($total), //总金额 单位 分
            'spbill_create_ip'  =>  $_SERVER['REMOTE_ADDR'], //终端IP
            'notify_url'        =>  \Yii::$app->params['domains']['api'].'/pay/pay-success', //通知地址 确保外网能正常访问
            'openid'            =>  $openid, // 用户的openid
            'trade_type'        =>  'JSAPI',//交易类型
            'time_start'        =>  date('YmdHis',time()),
            'time_expire'       =>  date('YmdHis',strtotime('+2 hours')),
        ];

        // 过滤掉无用参数.
        foreach($data as $key=>$value)
        {
            if(empty($data[$key])){
                unset($data[$key]);
            }
        }
        ksort($data);
        $data['key'] = \Yii::$app->params['wechat']['key'];
        $data['sign'] = strtoupper(md5(urldecode(http_build_query($data))));
        unset($data['key']);
        // 这里可能是xml
        $ret = HttpClient::post($url,CommonService::arrayToXml($data));
        if(!$ret)
        {
            return false;
        }

        $result = CommonService::xmlToArray($ret);

        if($result['return_code'] == 'FAIL'){
            // 配置出毛病了
            var_dump($result);exit;
            return false;
        }

        $return = [
            'appId'     =>  $data['appid'],
            'timeStamp' =>  $now,
            'nonceStr'  =>  $data['nonce_str'],
            'package'   =>  'prepay_id=' . $result['prepay_id'],
            'signType'  =>  'MD5'
        ];

        ksort($return);
        $return['key'] = \Yii::$app->params['wechat']['key'];
        $return['paySign'] = strtoupper(md5(urldecode(http_build_query($return))));
        unset($return['key']);
        unset($return['appId']);
        return $return;
    }

    /**
     * 申请退款
     * @param string $appid appid
     * @param string $mch_id mch_id
     * @param string $transaction_id  流水号
     * @param string $out_refund_no 退款订单号
     * @param string $total_fee 订单金额
     * @param string $refund_fee 退款金额
     * @param string $wechat_key 商户key
     * @return bool|array
     */
    public static function applyRefund($appid = '',$mch_id = '',$transaction_id = '',$out_refund_no = '',$total_fee = '',$refund_fee = '',$wechat_key = '')
    {

        $url = 'https://api.mch.weixin.qq.com/secapi/pay/refund';
        $now = time();
        $data = [
            'appid'             =>  $appid, //小程序ID
            'mch_id'            =>  (string)$mch_id, //商户号
            'nonce_str'         =>  md5($now),
            'transaction_id'      =>  $transaction_id, //流水号
            'out_refund_no'      =>  $out_refund_no, //商户退款订单号
            'total_fee'         =>  intval($total_fee), //总金额 单位 分
            'refund_fee'         =>  intval($refund_fee), //退款金额 单位 分
        ];

        // 过滤掉无用参数.
        foreach($data as $key=>$value)
        {
            if(empty($data[$key])){
                unset($data[$key]);
            }
        }
        ksort($data);
        $data['key'] = $wechat_key;
        $data['sign'] = strtoupper(md5(urldecode(http_build_query($data))));
        unset($data['key']);
        $files = [
            'cert' => \Yii::$app->getVendorPath('cert').'/../cert/apiclient_cert.pem',
            'key' => \Yii::$app->getVendorPath('cert').'/../cert/apiclient_key.pem',

        ];
        HttpClient::$files = $files;

        $ret = HttpClient::post($url,CommonService::arrayToXml($data),true);
        if(!$ret)
        {
            return false;
        }

        $result = CommonService::xmlToArray($ret);

        if($result['return_code'] == 'FAIL'){
            // 配置出毛病了
            var_dump($result);exit;
            return false;
        }
        return $result;
    }

    /**
     * 企业付款到银行卡
     * @param string $mch_id 商户号
     * @param string $partner_trade_no 商户企业付款单号
     * @param string $enc_bank_no 收款方银行卡号
     * @param string $enc_true_name 收款方用户名
     * @param string $bank_code 开户行编码
     * @param string $amount 付款金额
     * @param string $wechat_key 商户key
     * @param string $desc 付款说明
     * @return bool|mixed
     */
    public static function payBank($mch_id = '',$partner_trade_no = '',$enc_bank_no = '',$enc_true_name = '',$bank_code = '',$amount = '',$wechat_key = '',$desc = ''){
        $url = 'https://api.mch.weixin.qq.com/mmpaysptrans/pay_bank';
        $now = time();
        $data = [
            'mch_id' => $mch_id,
            'partner_trade_no' => $partner_trade_no,
            'nonce_str'=> md5($now),
            'enc_bank_no' => self::_getpublickey($mch_id,$wechat_key,$enc_bank_no),
            'enc_true_name' => self::_getpublickey($mch_id,$wechat_key,$enc_true_name),
            'bank_code' => $bank_code,
            'amount' => (integer)$amount,
            'desc' => $desc

        ];
        foreach($data as $key=>$value)
        {
            if(empty($data[$key])){
                unset($data[$key]);
            }
        }
        ksort($data);
        $data['key'] = $wechat_key;
        $data['sign'] = strtoupper(md5(urldecode(http_build_query($data))));
        unset($data['key']);
        $files = [
            'cert' => \Yii::$app->getVendorPath('cert').'/../cert/apiclient_cert.pem',
            'key' => \Yii::$app->getVendorPath('cert').'/../cert/apiclient_key.pem',

        ];
        HttpClient::$files = $files;

        $ret = HttpClient::post($url,CommonService::arrayToXml($data),true);
        if(!$ret)
        {
            return false;
        }

        $result = CommonService::xmlToArray($ret);

        if($result['return_code'] == 'FAIL'){
            // 配置出毛病了
//            var_dump($result);exit;
            return false;
        }
        return $result;

    }


    /**
     * 获取公钥并加密
     * @param string $mch_id
     * @param string $wechat_key
     * @return bool|mixed
     */
    private static function _getpublickey($mch_id = '',$wechat_key = '',$data = ''){
        //判断文件是否存在
        $file_path =  __DIR__ . '/public.pem';
        $content = file_get_contents($file_path);
        if(strlen($content) < 10){
            $url = 'https://fraud.mch.weixin.qq.com/risk/getpublickey';
            $now = time();
            $data = [
                'mch_id' => $mch_id,
                'nonce_str' => md5($now),
                'sign_type' => 'MD5',
            ];
            ksort($data);
            $data['key'] = $wechat_key;
            $data['sign'] = strtoupper(md5(urldecode(http_build_query($data))));
            unset($data['key']);
            $files = [
                'cert' => \Yii::$app->getVendorPath('cert').'/../cert/apiclient_cert.pem',
                'key' => \Yii::$app->getVendorPath('cert').'/../cert/apiclient_key.pem',

            ];
            HttpClient::$files = $files;

            $ret = HttpClient::post($url,CommonService::arrayToXml($data),true);
            if(!$ret)
            {
                return false;
            }

            $result = CommonService::xmlToArray($ret);

            if($result['return_code'] == 'FAIL'){
                // 配置出毛病了
                var_dump($result);exit;
                return false;
            }
            $content = $result['pub_key'];
            file_put_contents($file_path,$content);
        }
        //格式转换 PKCS#1 转 PKCS#8:
//        openssl rsa -RSAPublicKey_in -in <filename> -pubout
        $public_key = shell_exec("openssl rsa -RSAPublicKey_in -in  $file_path -pubout");
        //加密
        $encrypt_data = '';
        openssl_public_encrypt($data,$encrypt_data,$public_key,OPENSSL_PKCS1_OAEP_PADDING);
        $encrypt_data = base64_encode($encrypt_data);

        return $encrypt_data;
    }

    /**
     * 企业付款到微信零钱  微信商户后台必须设置开启 企业转账到微信零钱功能
     * @param string $mch_appid appid
     * @param string $mchid 商户号
     * @param string $partner_trade_no 订单号
     * @param string $openid 用户openid
     * @param string $amount 金额
     * @param string $desc 备注 必须填
     * @param string $wechat_key key
     * @return bool|mixed
     */
    public static function pay_transfers($mch_appid = '',$mchid = '',$partner_trade_no = '',$openid = '',$amount = '',$desc = '',$wechat_key = ''){
        $url = 'https://api.mch.weixin.qq.com/mmpaymkttransfers/promotion/transfers';
        $now = time();
        $data = [
          'mch_appid' => $mch_appid,
          'mchid' => $mchid,
          'nonce_str' => md5($now),
          'partner_trade_no' => $partner_trade_no,
          'openid' =>$openid,
          'check_name' => 'NO_CHECK',
          'amount' => (integer)$amount,
          'desc' => $desc,
          'spbill_create_ip' => $_SERVER['REMOTE_ADDR']

        ];
        // 过滤掉无用参数.
        foreach($data as $key=>$value)
        {
            if(empty($data[$key])){
                unset($data[$key]);
            }
        }
        ksort($data);
        $data['key'] = $wechat_key;
        $data['sign'] = strtoupper(md5(urldecode(http_build_query($data))));
        unset($data['key']);
        $files = [
            'cert' => \Yii::$app->getVendorPath('cert').'/../cert/apiclient_cert.pem',
            'key' => \Yii::$app->getVendorPath('cert').'/../cert/apiclient_key.pem',

        ];
        HttpClient::$files = $files;

        $ret = HttpClient::post($url,CommonService::arrayToXml($data),true);
        if(!$ret)
        {
            return false;
        }

        $result = CommonService::xmlToArray($ret);

        if($result['return_code'] == 'FAIL'){
            // 配置出毛病了
//            var_dump($result);exit;
            return false;
        }
        return $result;
    }




}